﻿using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using NLog;
using StudentManagement.Model.Exceptions;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Threading;
using WeihanLi.Extensions.Localization.Json;

namespace StudentManagement
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App : Application
    {
        /// <summary>
        /// 跨进程唯一标识
        /// </summary>
        private Mutex _mutex;

        protected override void OnStartup(StartupEventArgs e)
        {
            //防止程序重复运行
            this.Startup += new StartupEventHandler(App_Startup);
            //UI线程未捕获异常处理事件
            DispatcherUnhandledException += new DispatcherUnhandledExceptionEventHandler(App_DispatcherUnhandledException);
            //Task线程内未捕获异常处理事件
            TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
            //非UI线程未捕获异常处理事件
            AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

            Init();

            base.OnStartup(e);
        }

        private void App_Startup(object sender, StartupEventArgs e)
        {
            _mutex = new Mutex(true, "cluyun" + nameof(StudentManagement), out bool ret);
            if (!ret)
            {
                "程序已经在运行中... 如需重启请关闭后再重新打开。".ShowWarningAlert();
                Environment.Exit(0);
            }
        }

        private void App_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
        {
            e.Handled = true; //把 Handled 属性设为true，表示此异常已处理，程序可以继续运行，不会强制退出      
            HandlException(e.Exception);
        }

        private void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
        {
            //task线程内未处理捕获
            HandlException(e.Exception);
            e.SetObserved();//设置该异常已察觉（这样处理后就不会引起程序崩溃）
        }

        private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            HandlException(e.ExceptionObject as Exception);
        }

        /// <summary>
        /// 通用的处理异常方法
        /// </summary>
        /// <param name="ex"></param>
        private void HandlException(Exception ex)
        {
            if (ex == null) return;

            if (ex is BusinessExeption)
            {
                //业务上发生了错误
                ex.Message.ShowInfoAlert();
            }
            else
            {
                if (ex is HttpRequestException || ex is WebException)
                {
                    $"网络错误，请检查您的网络。{ex.Message}".ShowInfoAlert();
                }
                else
                {
                    "系统出现未知异常，请重启系统或联系供应商！".ShowErrorAlert();
                }

                //记录错误日志
                LogManager.GetCurrentClassLogger().Error(ex);
            }
        }

        private void ConfigureServices(IServiceCollection services)
        {
            #region 注入所有窗口
            {
                var winTypes = GetType().Assembly.GetTypes().Where(p => p.BaseType == typeof(Window));
                foreach (var winType in winTypes)
                {
                    services.TryAddTransient(winType);
                }
            }
            #endregion

            services.AddJsonLocalization(options => options.ResourcesPathType = ResourcesPathType.CultureBased);

            #region 批量注入Repository层和Service层的服务
            {
                string nav = nameof(StudentManagement), rep = nameof(StudentManagement.Repository), ser = nameof(StudentManagement.Service);
                var ts = Assembly.Load($"{nav}.{rep}").GetTypes().Concat(Assembly.Load($"{nav}.{ser}").GetTypes());
                var strOrd = StringComparison.OrdinalIgnoreCase;
                var examples = ts.Where(s => !s.IsInterface && (s.Name.EndsWith(rep, strOrd) || s.Name.EndsWith(ser, strOrd)));
                foreach (var example in examples)
                {
                    var interfaceTypes = example.GetInterfaces().Where(s => s.IsInterface && (s.Name.EndsWith(rep, strOrd) || s.Name.EndsWith(ser, strOrd)));
                    foreach (var interfaceType in interfaceTypes)
                    {
                        services.AddScoped(interfaceType, example);
                    }
                }
            }
            #endregion

        }

        private void Init()
        {
            Thread.CurrentThread.CurrentCulture = Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("zh-CHS");

            IServiceCollection services = new ServiceCollection();

            ConfigureServices(services);

            ServiceLocator.Instance = services.BuildServiceProvider();

            ServiceLocator.GetWindow<MainWindow>().Show();
        }
    }
}
